﻿/**************************************************************
 *
 * 唯一标识：93de1631-661c-4c84-b470-498d43267416
 * 命名空间：Sgr.IntegrationEvents
 * 创建时间：2023/8/19 21:13:34
 * 机器名称：DESKTOP-S0D075D
 * 创建者：antho
 * 电子邮箱：fengqinhua2016@163.com
 * 描述：
 *
 **************************************************************/

using FluentValidation;
using Sgr.Indentity.Application.Commands;
using Sgr.Indentity.Application.Validations;
using Sgr.Modules;
using Sgr.Utilities;
using System.Threading.RateLimiting;

namespace Sgr.Identity
{
    public class ModuleStartup : ModuleStartupBase
    {
        public override int Order => 100;

        /// <summary>
        /// 初始化HTTP请求管道初始化
        /// </summary>
        /// <param name="app"></param>
        /// <param name="env"></param>
        public override void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
        }

        /// <summary>
        /// 模块服务初始化
        /// </summary>
        /// <param name="services"></param>
        public override void ConfigureServices(IServiceCollection services)
        {
            services.AddEmail();
            services.AddSms();

            services.AddRateLimiter(options =>
            {
                string strPermitLimit = EnvironmentHelper.GetEnvironmentVariable("SGR_PERMIT_LIMIT") ?? "10";

                if (!int.TryParse(strPermitLimit, out int permitLimit))
                    permitLimit = 10;

                // 登录接口限流策略 - 防止暴力破解但允许正常用户操作
                options.AddPolicy("RateLimiterPolicy.Sgr.Identity.Login", httpContext =>
                    RateLimitPartition.GetFixedWindowLimiter(
                        partitionKey: httpContext.GetClientIpAddress(),
                        factory: partition => new FixedWindowRateLimiterOptions
                        {
                            AutoReplenishment = true,
                            PermitLimit = permitLimit,            // 每个窗口允许10次尝试
                            Window = TimeSpan.FromMinutes(3),     // 3分钟窗口
                            QueueLimit = 0                        // 不允许排队
                        }));

                // 添加验证码的限流策略
                options.AddPolicy("RateLimiterPolicy.Sgr.Identity.VerifyCode", httpContext =>
                    RateLimitPartition.GetFixedWindowLimiter(
                        partitionKey: httpContext.GetClientIpAddress(),
                        factory: partition => new FixedWindowRateLimiterOptions
                        {
                            AutoReplenishment = true,
                            PermitLimit = permitLimit,          // 允许的请求数
                            QueueLimit = 0,                     // 队列限制
                            Window = TimeSpan.FromMinutes(1)    // 时间窗口
                        }));

                // 其他认证接口限流策略 - 较为宽松
                options.AddPolicy("RateLimiterPolicy.Sgr.Identity", httpContext =>
                    RateLimitPartition.GetFixedWindowLimiter(
                        partitionKey: httpContext.GetClientIpAddress(),
                        factory: partition => new FixedWindowRateLimiterOptions
                        {
                            AutoReplenishment = true,
                            PermitLimit = permitLimit * 3,        // 每个窗口允许30次尝试
                            Window = TimeSpan.FromMinutes(3),     // 3分钟窗口
                            QueueLimit = 0
                        }));
            });

            services.AddTransient<IValidator<SendVerificationCodeCommand>, SendVerificationCodeCommandValidator>();

            //注册MediatR
            services.AddMediatR(cfg =>
            {
                cfg.RegisterServicesFromAssemblyContaining<ModuleStartup>();
            });
        }
    }
}